#include "thread_manage.h"

#ifndef TM_DBG
#define TM_DBG(format, argument...)    do{ printf("[ %s ]  %s (line %d) -> " format"\r\n", __FUNCTION__,  __FILE__ ,__LINE__, ##argument ); }while(0)
#endif
#define THREAD_EVENT_PATH	"/tmp/"

#define MONITOR_TIME_OUT			1000//监控间隔时间
#define MONITOR_HEART_CNT_WARN		10	//线程超过10 * 1000ms没有执行os_monitor_delay 就进行预警

typedef enum
{
    THREAD_MONITOR_EVENT_ID_IWDT = 1,	//表示线程活跃状态
		
}THREAD_MONITOR_EVENT_ID_E;
#define MONITOR_THREAD	"os_monitor_thread"

static int get_thread_info(t_thread_info *thread_info);
static int get_thread_info_by_thread_name(char *name, t_thread_info *thread_info);
static int get_thread_info_by_thread_tid(pthread_t tid, t_thread_info *thread_info);
static int thread_monitor_process(void);

static int clean_thread_heart_by_thread_tid(pthread_t tid);

typedef struct	_t_thread_manage_arg{

	int init;
	t_thread_mutex mutex;				//互斥锁
	int os_monitor_enable;				//线程监控开关
	t_thread_info thread_info_list;
}t_thread_manage_arg;

static t_thread_manage_arg s_thread_manage_arg;

static void os_mutex_lock(void)
{
    md_thread_mutex_lock(&s_thread_manage_arg.mutex);
}

static void os_mutex_unlock(void)
{
    md_thread_mutex_unlock(&s_thread_manage_arg.mutex);
}

/** 
 * @brief 
 * @param               
 * 
 * @return 
 */
int os_monitor_sleep(uint32_t u32ms)
{
	int monitor_is_enable = 0;
	os_mutex_lock();
	monitor_is_enable = s_thread_manage_arg.os_monitor_enable;
	os_mutex_unlock();
	if(monitor_is_enable){
		pthread_t *arg = malloc(sizeof(pthread_t));
		*arg = pthread_self();
		thread_manage_event_msg_send(MONITOR_THREAD, THREAD_MONITOR_EVENT_ID_IWDT, arg);
	}
	if(u32ms == 0){
		return 0;
	}
    if(u32ms/1000)
    {
        for(int i = 0;i < (u32ms/1000);i++)
        {
            usleep(1000 * 1000);   
        }
        usleep(u32ms%1000); 
    }
    else{
        usleep(u32ms%1000); 
    }   
    return 0;
}

static int iwdt_event_callback(t_event_listen *event, void *arg)
{
	pthread_t *tid = (pthread_t *)arg;
	t_thread_info info ;
	memset(&info, 0x00, sizeof(t_thread_info));
#if 1
	if(get_thread_info_by_thread_tid(*tid, &info) >= 0){
		TM_DBG("pthread_t name %s",info.thread_name);
	}
#endif
	clean_thread_heart_by_thread_tid(*tid);
	
	if(arg)
		free(arg);
	return 0;
}
/** 
 * @brief 线程管理自带的县城监控模块任务
 * @param               
 * 
 * @return 
 */
static void *os_monitor_task( void *arg )  
{  
	thread_manage_event_listen(THREAD_MONITOR_EVENT_ID_IWDT, NULL, iwdt_event_callback );
	while(1){
		thread_manage_event_listen_process(EVENT_PROCESS_NON_BLOCK);

		thread_monitor_process();
		os_monitor_sleep(MONITOR_TIME_OUT);
	} 
}  


/** 
 * @brief 线程管理初始化
 			1：调用线程监控  、线程事件等相关初始化接口
 			2：线程管理接口资源锁初始化
 * @param  bool is_enable -> 0:关闭线程监控  1:开启线程监控             
 * 
 * @return 返回资源初始化结果
 */
int thread_manage_init(int is_enable)
{
	int ret = -1;
	ret = md_thread_mutex_init(&s_thread_manage_arg.mutex,(char*)"thread_manage");
	memset(&s_thread_manage_arg.thread_info_list,0x00,sizeof(t_thread_info));
    INIT_LIST_HEAD(&s_thread_manage_arg.thread_info_list.list);
	s_thread_manage_arg.os_monitor_enable = is_enable;
	s_thread_manage_arg.init = 1;

	//创建监控线程，并且添加注册事件
	t_thread_info *p = thread_info_malloc(MONITOR_THREAD);
	if(NULL == p){
		TM_DBG( "thread_info_malloc %s error! ",MONITOR_THREAD);   
	}
	ret = thread_manage_member_add(p, THREAD_EVENT_ENABLE);
	if( ret != 0 ){
		TM_DBG( "thread_manage_member_add error! ");   
	}else{
		TM_DBG( "thread num is %d",p->num);  
	}
	ret = md_set_stacksize_create_thread(MONITOR_THREAD, &p->thread_arg, (2 * 1024), os_monitor_task, NULL );  
    if( ret != 0 ){  
        TM_DBG( "create %s error! ",MONITOR_THREAD);   
    }
 	TM_DBG("thread_manage init .p->msqid %d",p->msqid);
	return ret;
}

/** 
 * @brief 线程创建时的资源申请
 * @param      name：线程命名         
 * 
 * @return 
 */
t_thread_info *thread_info_malloc(char *name)
{
	if(NULL == name){
		return NULL;
	}
	t_thread_info *p = malloc(sizeof(t_thread_info));
	if(NULL == p){
		goto EXIT;
	}
	memset(p, 0x00, sizeof(t_thread_info));
	p->thread_name = malloc(strlen(name) + 1);
	if(NULL == p){
		goto EXIT;
	}
	strncpy(p->thread_name, name, strlen(name));
	p->heart_cnt = 0;
	return p;
EXIT:
	if(p){
		if(p->thread_name)free(p->thread_name);
		free(p);
	}
	return NULL;
}

/** 
 * @brief 线程删除时需要进行的资源释放
 * @param   thread_info：节点指针            
 * 
 * @return 
 */
void thread_info_free(t_thread_info *thread_info)
{
	if(thread_info){
		if(thread_info->thread_name)free(thread_info->thread_name);
		free(thread_info);
	}
}

/** 
 * @brief 线程监控主循环
 * @param               
 * 
 * @return 
 */
static int thread_monitor_process(void)
{
	int ret = -1;
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		tmp->heart_cnt++;
		if(tmp->heart_cnt >= MONITOR_HEART_CNT_WARN){
			TM_DBG(" \\*******************OS MONITOR WARN**********************\\ ");
			TM_DBG(" block thread name:%s ",tmp->thread_name);
			TM_DBG(" \\*******************OS MONITOR WARN**********************\\ ");
		}
		ret = 0;
	}
	os_mutex_unlock();
	return ret;
}


/** 
 * @brief 指定tid，清空其心跳计数器
 * @param               tid:指定的线程id
 * 
 * @return 
 */
static int clean_thread_heart_by_thread_tid(pthread_t tid)
{
	int ret = -1;
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		if(tid == tmp->thread_arg)
		{
			tmp->heart_cnt = 0;
			ret = 0;
		}
	}
	os_mutex_unlock();
	return ret;
}


/** 
 * @brief 指定tid，获取线程信息
 * @param               name:指定的线程id
 						thread_info：传出的线程信息
 * 
 * @return 
 */
static int get_thread_info_by_thread_tid(pthread_t tid, t_thread_info *thread_info)
{
	int ret = -1;
	if(NULL == thread_info){
		return ret;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		if(tid == tmp->thread_arg)
		{
			memcpy(thread_info, tmp, sizeof(t_thread_info));
			ret = 0;
		}
	}
	os_mutex_unlock();
	return ret;
}

/** 
 * @brief 指定名称，获取线程信息
 * @param               name:指定的线程名称
 						thread_info：传出的线程信息
 * 
 * @return 
 */
static int get_thread_info_by_thread_name(char *name, t_thread_info *thread_info)
{
	int ret = -1;
	if(NULL == thread_info){
		return ret;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		if(strcmp(name, tmp->thread_name) == 0)
		{
			memcpy(thread_info, tmp, sizeof(t_thread_info));
			ret = 0;
		}
	}
	os_mutex_unlock();
	return ret;
}

/** 
 * @brief 获取当前线程的线程信息
 * @param         thread_info：传出的线程信息      
 * 
 * @return 
 */
static int get_thread_info(t_thread_info *thread_info)
{
	int ret = -1;
	if(NULL == thread_info){
		return ret;
	}
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	pthread_t tid = pthread_self();
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		if(tid == tmp->thread_arg)
		{
			memcpy(thread_info, tmp, sizeof(t_thread_info));
			ret = 0;
		}
	}
	os_mutex_unlock();
	return ret;
}

/** 
 * @brief 线程管理单位成员添加，往线程列表尾部添加一个线程信息
 * @param           thread_info：线程信息    
 * 
 * @return 
 */
int thread_manage_member_add(t_thread_info *thread_info, THREAD_EVENT_TYPE_E e)
{
	static uint8_t num = 0;
	os_mutex_lock();
	if(s_thread_manage_arg.init != 1){
		os_mutex_unlock();
		return -1;
	}
	list_add_tail(&thread_info->list, &s_thread_manage_arg.thread_info_list.list);
	num++;
	thread_info->num = num;
	if(THREAD_EVENT_ENABLE == e){
		thread_info->msqid = event_module_add_init(thread_info->num, &thread_info->event_listen_list);	//阻塞事件
	}
	os_mutex_unlock();
	return 0;
}

/** 
 * @brief 线程管理单位成员删除，线程列表中删除相关单元成员
 * @param              event_used：创建该线程时是否使用了事件功能
 * 
 * @return 
 */
int thread_manage_member_del(int event_used)
{
	struct list_head *pos =NULL,*n=NULL;
	t_thread_info *tmp = NULL;
	pthread_t tid = pthread_self();
	os_mutex_lock();
	list_for_each_safe(pos, n, &s_thread_manage_arg.thread_info_list.list)
	{
		// 这里我们用list_entry来取得pos所在的结构的指针
		tmp = list_entry(pos, t_thread_info, list);
		if(NULL == tmp){
			break;
		}
		if(tid == tmp->thread_arg)
		{
			TM_DBG("del thread name:%s ", tmp->thread_name);
			list_del_init(pos);
			if(event_used){
				//如果使用了事件功能，则删除该事件
				event_module_del_deinit(tmp->msqid, &tmp->event_listen_list);
			}
			thread_info_free(tmp);
		}
	}
	os_mutex_unlock();
	return 0;
}

/** 
 * @brief 线程管理模块事件监听接口，往当前线程对应的事件模块中添加
 * @param       event_id：事件id   
 				user_data：用户参数
 				cb：事件回调
 * 
 * @return 
 */
int thread_manage_event_listen(int event_id, void *user_data, event_callback_func cb)
{
	t_thread_info info ;
	memset(&info, 0x00, sizeof(t_thread_info));
	pthread_t tid = pthread_self();
	if(get_thread_info(&info) < 0){
		return -1;
	}
	event_listen(&info.event_listen_list, event_id, user_data, cb);
	return 0;
}

/** 
 * @brief 线程管理模块事件取消监听接口，往当前线程对应的事件模块中删除
 * @param      event_id：事件id         
 * 
 * @return 
 */
int thread_manage_event_unlisten(int event_id)
{
	t_thread_info info ;
	memset(&info, 0x00, sizeof(t_thread_info));
	pthread_t tid = pthread_self();
	if(get_thread_info(&info) < 0){
		return -1;
	}
	event_unlisten(&info.event_listen_list, event_id);
	return 0;

}

/** 
 * @brief 线程管理事件模块处理主流程，非阻塞
 * @param               
 * 
 * @return 0:超时
 */
int thread_manage_event_listen_process(EVENT_PROCESS_E type)
{
	int ret = 0; 
	t_thread_info info ;
	memset(&info, 0x00, sizeof(t_thread_info));
	pthread_t tid = pthread_self();
	if(get_thread_info(&info) < 0){
		return -1;
	}
	for(;;){
		ret = event_listen_process(info.msqid, &info.event_listen_list, type);
		if(ret <= 0){
			break;
		}
	}
	return ret;
}

/** 
 * @brief 线程管理模块事件发送接口，需要指定接收方的线程名称
 * @param              thread_name：对方的线程名称
 						event_id：事件id
 						arg：参数
 * 
 * @return 
 */
int thread_manage_event_msg_send(char * thread_name, int event_id, void *arg )
{
	t_thread_info info ;
	memset(&info, 0x00, sizeof(t_thread_info));
	pthread_t tid = pthread_self();
	if(get_thread_info_by_thread_name(thread_name, &info) < 0){
		return -1;
	}
	int ret = event_msg_send(info.msqid, event_id, arg);
	return ret;
}


